#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include "HTTPServer.hpp"

namespace icecode {
  namespace http {
    HTTPServer::HTTPServer(HTTPServer::HTTPOptions *opts)
    {
      if(opts)
	this->opts = *opts;

      quit = false;
      errcount = 0;
      connections = 0;
    }

    HTTPServer::~HTTPServer()
    {
    }

    void HTTPServer::run()
    {
      int sock = socket(AF_INET, SOCK_STREAM, 0);

      if(sock == -1) //error
	{} //TODO: Throw exception
      else
	{
	  struct sockaddr saddr = {0}; //TODO: Fill structure

	  if(bind(sock, &saddr, sizeof(saddr)) == -1)
	    { //TODO: Throw exception
	    }
	  else
	    {
	      while(!quit)
		{
		  if((connections < opts.max_conn))
		    {
		      int conn = accept(sock, &saddr, sizeof(saddr));
		  
		      if(conn == -1) //error
			{
			  errcount++;
			  usleep(1000);
			  continue;
			}
		      else
			{ //socket connected, run an instance
			  if(fork() == 0)
			    {
			      //TODO: Handle HTTP requests
			      close(conn);
			      exit(0);
			    }
			  close(conn);
			}
		    } else usleep(500); //no slot available, wait some time to save CPU.
		}
	    }

	  close(sock);
	}
    }

    HTTPServer::HTTPOptions& HTTPServer::HTTPOptions::operator =(const HTTPServer::HTTPOptions &opts)
    {
      root_dir = opts.root_dir;
      listen_addr = opts.listen_addr;
      listen_port = opts.listen_port;
      max_conn = opts.max_conn;

      return *this;
    }
  }
}
